package cn.ingrun.utils.redisCache.aspect;

import cn.ingrun.utils.auth.LoginAuthAspect;
import cn.ingrun.utils.redisCache.inter.EnableRedisCache;
import cn.ingrun.utils.redisCache.server.RedisCacheServer;
import cn.ingrun.utils.redisUtil.RedisUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class RedisCache {

    private final static Logger logger = LoggerFactory.getLogger(LoginAuthAspect.class);

    private RedisUtil redisUtil;
    private RedisCacheServer redisCacheServer;
    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Autowired
    public void setRedisCacheServer(RedisCacheServer redisCacheServer) {
        this.redisCacheServer = redisCacheServer;
    }

    // 环绕通知：环绕目标方式执行
    @Around("@annotation(cn.ingrun.utils.redisCache.inter.EnableRedisCache)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{

        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName(); // 方法名
        Class<?> methodReturnType = method.getReturnType(); // 方法返回类型
        String[] parameterNames = signature.getParameterNames();   // 方法参数名数组
        Object[] args = pjp.getArgs(); // 方法参数值数组

        String redisKey = redisCacheServer.getRedisCacheKey(methodName, parameterNames, args);
        if (redisUtil.hasKey(redisKey)) {
            try {
                logger.info( "获取缓存值" );
                return redisCacheServer.getCache(redisKey, methodReturnType);
            }catch (RuntimeException e){
                logger.warn(e.toString());
                logger.info( "获取缓存值失败，删除缓存,调用原方法" );
                redisCacheServer.delCache(redisKey);
                return pjp.proceed();
            }
        }

        Object obj =  pjp.proceed();  // 执行目标方法
        EnableRedisCache annotation = method.getAnnotation(EnableRedisCache.class);  // 获得自定义缓存时间
        redisCacheServer.addCache(redisKey, obj, annotation.cacheTime());
        return obj;
    }

}
